const nop = () => {
};
const HEARTBEAT_INTERVAL = 30 * 1000;

class DeviceController {
    connected = false;
    wsClient = null;
    waiting = false;
    onComplete = nop;
    _wsId = 1;

    constructor(options) {
        const {url, token, onConnected, onDisconnect} = options;
        this.onConnected = onConnected || nop;
        this.onDisconnect = onDisconnect || nop;
        this.url = url + '?token=' + token;
        this.heartbeatTimer = null;
    }

    connect() {
        if (this.connected) {
            return;
        }
        if (this.wsClient) {
            this.disconnect();
        }
        this.wsClient = new WebSocket(this.url);
        this.wsClient.wsId = this._wsId++;
        this.wsClient.onopen = () => {
            this.onSocketOpen();
        };
        this.wsClient.onmessage = e => {
            this.onMessage(e);
        };
        this.wsClient.onclose = () => {
            this.onClose();
        };
        this.wsClient.onError = e => {
            this.onError(e);
        };
    }

    onError(e) {
        console.log('wsError', e, this.wsClient && this.wsClient.wsId);
        this.disconnect();
        this.onDisconnect();
    }

    unbindEvent() {
        if (!this.wsClient) {
            return;
        }
        this.wsClient.onopen = null;
        this.wsClient.onclose = null;
        this.wsClient.onmessage = null;
        this.wsClient.onerror = null;
    }

    onClose() {
        console.log('WS Close', this.wsClient && this.wsClient.wsId);
        this.unbindEvent();
        this.wsClient = null;
        this.disconnect();
        this.onDisconnect();
    }

    onMessage(e) {
        this.waiting = false;
        const data = JSON.parse(e.data);
        console.log('CTL<<<:', data);
        this.onComplete && this.onComplete(data);
        this.onComplete = nop;
    }

    disconnect() {
        this.connected = false;
        if (this.wsClient) {
            this.wsClient.close();
            console.log('WS DoClose', this.wsClient && this.wsClient.wsId);
        }
        this.wsClient = null;
    }

    onSocketOpen() {
        console.log('WS Open', this.wsClient && this.wsClient.wsId);
        this.connected = true;
        this.onConnected();
        this.resetHeartbeat();
    }

    resetHeartbeat() {
        if (this.heartbeatTimer) {
            clearTimeout(this.heartbeatTimer);
            this.heartbeatTimer = null;
        }
        this.heartbeatTimer = setTimeout(() => this.sendHeartbeat(), HEARTBEAT_INTERVAL);
    }

    sendHeartbeat() {
        if (!this.wsClient) {
            this.connect();
        }
        const heartbeat = {};
        this.wsSend(JSON.stringify(heartbeat));
        console.log('>>> Heartbeat');
        this.heartbeatTimer = setTimeout(() => this.sendHeartbeat(), HEARTBEAT_INTERVAL);
    }

    deviceCtl(option) {
        if (this.waiting) {
            return false;
        }
        this.waiting = true;
        const {deviceId, status, onComplete} = option;
        this.onComplete = onComplete;
        const ctlPkt = {
            deviceId: deviceId,
            status: status,
        };
        if (!this.wsClient) {
            alert('重连服务器，请稍后。。。');
            this.waiting = false;
            return;
        }
        console.log('CTL >>>:', ctlPkt);
        this.wsSend(JSON.stringify(ctlPkt));
        return true;
    }

    wsSend(payload) {
        if (!this.wsClient || this.wsClient.readyState !== WebSocket.OPEN) {
            console.error('WebSocket not ready!expect send', payload);
            return;
        }
        this.wsClient.send(payload);
    }
}

export default DeviceController;